#include "stdafx.h"

namespace cpputils
{

logger::task::task(logger* SetLogger)
	: Logger(0)
{
	begin(SetLogger);
}

logger::task::task(const task& Val)
	: Logger(0)
{
	*this = Val;
}

logger::task::~task()
{
	end();
}

logger::task& logger::task::operator=(const task& Val)
{
	end();
	Logger = Val.Logger;
	Val.Logger = 0;
	Progress.swap(Val.Progress);
	return *this;
}

void logger::task::begin(logger* SetLogger)
{
	end();
	Logger = SetLogger;
	if (Logger != 0) Logger->indent(2);
}

void logger::task::end()
{
	progress("");
	if (Logger != 0) Logger->unindent(2);
	Logger = 0;
}

const string& logger::task::get_progress()
{
	return Progress;
}

void logger::task::progress(const string& S)
{
	Progress = S;
	if (Logger != 0) Logger->progress(S);
}

const string& logger::get_level_name(level Lev)
{
	static string Names[] =
	{"ALL", "FINEST", "FINER", "FINE", "CONFIG", "INFO", "WARNING", "SEVERE", "OFF"};
	return Names[Lev];
}

logger::logger(FILE* SetFile)
	: File(SetFile), Level(all_level), Indent(0), ProgressLen(0)
{
}

FILE* logger::get_file() const
{
	return File;
}

void logger::set_file(FILE* Val)
{
	File = Val;
}

logger::level logger::get_level() const
{
	return Level;
}

void logger::set_level(level Val)
{
	Level = Val;
}

int logger::get_indent() const
{
	return Indent;
}

void logger::set_indent(int Val)
{
	Indent = Val;
}

void logger::indent(int Val)
{
	Indent += Val;
}

void logger::unindent(int Val)
{
	Indent -= Val;
}

logger::task logger::log(level MsgLevel, const string& S)
{
	if (MsgLevel < Level) return task(0);
	clear_progress();
	checked_fprintf(File, "%-8s", get_level_name(MsgLevel).c_str());
	checked_fprintf(File, "%*s", Indent, "");
	checked_fprintf(File, "%s\n", S.c_str());
	return task(this);
}

logger::task logger::severe(const string& S)
{
	return log(severe_level, S);
}

logger::task logger::warning(const string& S)
{
	return log(warning_level, S);
}

logger::task logger::info(const string& S)
{
	return log(info_level, S);
}

logger::task logger::config(const string& S)
{
	return log(config_level, S);
}

logger::task logger::fine(const string& S)
{
	return log(fine_level, S);
}

logger::task logger::finer(const string& S)
{
	return log(finer_level, S);
}

logger::task logger::finest(const string& S)
{
	return log(finest_level, S);
}

void logger::progress(const string& S)
{
	clear_progress();
	checked_fprintf(File, "%s", S.c_str());
	ProgressLen = S.length();
}

void logger::clear_progress()
{
	if (ProgressLen == 0) return;
	checked_fprintf(File, "\r%*s\r", ProgressLen, "");
	ProgressLen = 0;
}

logger* nillogger()
{
	static logger Log;
	Log.set_file(0);
	Log.set_level(logger::off_level);
	return &Log;
}

logger* clogger()
{
	static logger Log;
	Log.set_file(stdout);
	return &Log;
}

}
